package com.logisticsrepair.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.logisticsrepair.customEntity.AnnouncementEntity;
import com.logisticsrepair.entity.ApplyMaterialEntity;
import com.logisticsrepair.entity.RepairOrdersEntity;
import com.logisticsrepair.entity.UserEntity;
import com.logisticsrepair.enums.RepairStatusEnum;
import com.logisticsrepair.service.ApplyMaterialService;
import com.logisticsrepair.service.RepairOrdersService;
import com.logisticsrepair.service.RepairStatusService;
import com.logisticsrepair.service.RepairTypeService;
import com.logisticsrepair.service.UserService;
import com.logisticsrepair.util.Public;
import com.logisticsrepair.util.RedisUtil;
import com.logisticsrepair.util.responseUtil.ResponseEnum;
import com.logisticsrepair.util.responseUtil.ResponseUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import redis.clients.jedis.Jedis;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.*;

@RestController
@RequestMapping("/userHome")
public class UserHomeController {
    static Jedis redis = RedisUtil.getRedis();

    public static final String ALL = "all";
    public static final String USER = "user";
    public static final String WORKER = "worker";
    private static final String PASSWORD_SALT = "123456"; // 密码加密盐值

    public static final HashMap<String, String> ANNOUNCEMENT_RANGE = new HashMap<>();

    static {
        ANNOUNCEMENT_RANGE.put(ALL, "announcement:all");
        ANNOUNCEMENT_RANGE.put(USER, "announcement:user");
        ANNOUNCEMENT_RANGE.put(WORKER, "announcement:worker");
    }

    @Autowired
    private RepairOrdersService repairOrdersService;

    @Autowired
    private RepairTypeService repairTypeService;

    @Autowired
    private RepairStatusService repairStatusService;

    @Autowired
    private ApplyMaterialService applyMaterialService;

    @Autowired
    private UserService userService;


    @RequestMapping("/createOrder")
    public ResponseUtil photo(@RequestParam(value = "file", required = false) MultipartFile[] files, String orderForm) {
        RepairOrdersEntity repairOrdersEntity = JSONObject.parseObject(orderForm, RepairOrdersEntity.class);

        repairOrdersEntity.setOrderId(DateUtil.format(new Date(), DatePattern.PURE_DATETIME_PATTERN) + RandomUtil.randomNumbers(6));

        String loginId = StpUtil.getLoginId().toString();
        repairOrdersEntity.setUserOpenid(loginId);
        repairOrdersEntity.setRepairDate(DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
        repairOrdersEntity.setStatusCode(RepairStatusEnum.TO_ACCEPT);
        List<String> imgUrl = new ArrayList<>();
        if (files != null) {
            for (MultipartFile file : files) {
                try {
                    File saveUserPhoto = Public.saveUserPhoto(file,loginId, repairOrdersEntity.getOrderId());
                    String absolutePath = saveUserPhoto.getAbsolutePath();
                    System.out.println("🖼️ 文件绝对路径: " + absolutePath);
                    String path = absolutePath.substring(absolutePath.indexOf("static") + 6, absolutePath.length());
                    // 将Windows路径分隔符 \ 替换为URL路径分隔符 /
                    path = path.replace("\\", "/");
                    System.out.println("🔗  数据库保存路径: " + path);
                    imgUrl.add(path);
                } catch (IOException e) {
                    System.err.println("❌ 图片保存失败！");
                    e.printStackTrace();
                } catch (Exception e) {
                    System.err.println("❌ 其他异常: " + e.getMessage());
                    e.printStackTrace();
                }
            }
        }
        if (!imgUrl.isEmpty()) {
            repairOrdersEntity.setImgUrl(JSON.toJSONString(imgUrl));
        }
        boolean save = repairOrdersService.save(repairOrdersEntity);
        if (save)
            return ResponseUtil.setE(ResponseEnum.OK);
        return ResponseUtil.setE(ResponseEnum.FAIL);
    }

    @GetMapping("/repairType")
    public ResponseUtil repairType() {
        return ResponseUtil.setE(ResponseEnum.OK).setData(repairTypeService.list());
    }

    @GetMapping("/repairStatus")
    public ResponseUtil repairStatus() {
        return ResponseUtil.setE(ResponseEnum.OK).setData(repairStatusService.list());
    }

    @GetMapping("/queryUserOrderRecord")
    public ResponseUtil queryUserOrderRecord() {
        String openid = StpUtil.getLoginId().toString();
        List<RepairOrdersEntity> orderFormEntityList = repairOrdersService.queryUserOrderRecode(openid);

        List<ApplyMaterialEntity> applyMaterialEntityList = applyMaterialService.queryUserWaitChargeOrder(openid);

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("orderFormEntityList", orderFormEntityList);
        hashMap.put("applyMaterialEntityList", applyMaterialEntityList);
        return ResponseUtil.setE(ResponseEnum.OK).setData(hashMap);
    }

    @PostMapping("/cancelOrder")
    public ResponseUtil cancelOrder(@RequestBody RepairOrdersEntity repairOrdersEntity) {
        LambdaQueryWrapper<RepairOrdersEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(RepairOrdersEntity::getStatusCode, repairOrdersEntity.getStatusCode())
                .eq(RepairOrdersEntity::getOrderId, repairOrdersEntity.getOrderId());
        boolean isRemove = repairOrdersService.remove(lambdaQueryWrapper);
        if (isRemove) {
            Public.deleteUserPhoto(StpUtil.getLoginId().toString(), repairOrdersEntity.getOrderId());
            return ResponseUtil.setE(ResponseEnum.OK).setMsg("取消成功!");
        }
        return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("取消失败，订单状态已更新!");
    }

    @PostMapping("/getPayHashCode")
    public ResponseUtil getPayHashCode(@RequestBody Map<String, Object> map) {
        if (map.isEmpty()) return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("订单信息错误");

        List<String> applyIds = JSONArray.parseArray(map.get("applyIds").toString(), String.class);
        String md5ApplyId = map.get("md5ApplyId").toString();
        String time = map.get("time").toString();

        // 修复MD5计算，使用JSON序列化后的字符串，和前端保持一致
        String applyIdsJson = JSON.toJSONString(applyIds);
        String md5ApplyId1 = DigestUtil.md5Hex(applyIdsJson + "/userHome/getPayHashCode" + time);
        if (!md5ApplyId1.equals(md5ApplyId)) {
            System.out.println("MD5验证失败！");
            System.out.println("前端传来的MD5: " + md5ApplyId);
            System.out.println("后端计算的MD5: " + md5ApplyId1);
            System.out.println("用于计算的字符串: " + applyIdsJson + "/userHome/getPayHashCode" + time);
            return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("订单信息错误1");
        }

        List<ApplyMaterialEntity> applyMaterialEntities = applyMaterialService.queryWaitPayOrderByApplyIdAs(applyIds);
        if (applyMaterialEntities.isEmpty()) return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("订单信息错误2");

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("applyIds", applyIds);
        hashMap.put("applyMaterialEntities", applyMaterialEntities);

        String md5Hex = DigestUtil.md5Hex(JSON.toJSONString(hashMap));

        redis.setex(md5Hex, 60 * 60 * 24, JSON.toJSONString(hashMap));

        return ResponseUtil.setE(ResponseEnum.OK).setData(md5Hex);
    }

    @PostMapping("/pay")
    public ResponseUtil pay(@RequestBody Map<String, Object> map) {
        if (map.isEmpty()) return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("订单信息错误");
        Object code = map.get("code");
        String socket = map.get("socket").toString();

        if (ObjectUtil.isEmpty(code) || !redis.exists(code.toString()))
            return ResponseUtil.setE(ResponseEnum.PARAMS_ERROR);

        HashMap<String, Object> redisData = JSONObject.parseObject(redis.get(code.toString()), HashMap.class);
        List<String> applyIds = JSONArray.parseArray(redisData.get("applyIds").toString(), String.class);
        String materialEntities = redisData.get("applyMaterialEntities").toString();

        List<ApplyMaterialEntity> applyMaterialEntities = JSONArray.parseArray(materialEntities, ApplyMaterialEntity.class);
        if (applyMaterialEntities.isEmpty()) return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("订单信息错误2");

        String uuid = IdUtil.simpleUUID();

        float totalPrice = 0;
        for (ApplyMaterialEntity k : applyMaterialEntities) {
            totalPrice += k.getMaterialPrice() * k.getTakeAmount();
        }
        totalPrice = NumberUtil.round(totalPrice, 1).floatValue();

        long timeMillis = System.currentTimeMillis();

        int expireMillis = 1000 * 60 * 60 * 2;

        HashMap<String, Object> hashMap = new HashMap<>();
        hashMap.put("uuid", uuid);
        hashMap.put("totalPrice", totalPrice);
        hashMap.put("timeMillis", timeMillis);
        hashMap.put("expireMillis", expireMillis);

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        QrCodeUtil.generate(JSON.toJSONString(hashMap), 300, 300, ImgUtil.IMAGE_TYPE_JPG, outputStream);
        String img = "data:image/jpg;base64," + Base64.encode(outputStream.toByteArray());

        hashMap.put("applyIds", applyIds);
        hashMap.put("img", img);
        hashMap.put("socket", socket);

        redis.del(code.toString());
        redis.setex(uuid, expireMillis / 1000, JSON.toJSONString(hashMap));

        hashMap.remove("applyIds");
        return ResponseUtil.setE(ResponseEnum.OK).setData(hashMap);
    }

    /**
     * 格式化从redis中获取的公告对象信息
     *
     * @param range 范围
     * @return
     */
    public static ArrayList<AnnouncementEntity> formatRedisAnnouncement(String range) {
        Map<String, String> map = redis.hgetAll(ANNOUNCEMENT_RANGE.get(range));
        Set<String> keySet = map.keySet();
        ArrayList<AnnouncementEntity> list = new ArrayList<>();
        for (String key : keySet) {
            list.add(JSON.parseObject(map.get(key), AnnouncementEntity.class));
        }
        return list;
    }

    @GetMapping("/pullAllAnnouncement")
    public ResponseUtil pullAllAnnouncement() {
        List<AnnouncementEntity> result = new ArrayList<>();
        if (redis.exists(ANNOUNCEMENT_RANGE.get(ALL))) {
            result.addAll(formatRedisAnnouncement(ALL));
        }
        if (redis.exists(ANNOUNCEMENT_RANGE.get(USER)) && StpUtil.getLoginType().equals(USER)) {
            result.addAll(formatRedisAnnouncement(USER));
        }
        if (redis.exists(ANNOUNCEMENT_RANGE.get(WORKER)) && StpUtil.getLoginType().equals(WORKER)) {
            result.addAll(formatRedisAnnouncement(WORKER));
        }
        if (!result.isEmpty()) return ResponseUtil.setE(ResponseEnum.OK).setData(result);
        return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("暂无公告");
    }

    /**
     * 修改用户密码
     */
    @SaCheckLogin
    @PostMapping("/updatePassword")
    public ResponseUtil updatePassword(@RequestBody Map<String, String> params) {
        try {
            String oldPassword = params.get("oldPassword");
            String newPassword = params.get("newPassword");
            
            // 参数验证
            if (oldPassword == null || newPassword == null) {
                return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("参数不能为空");
            }
            
            if (newPassword.length() < 6) {
                return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("新密码长度不能少于6位");
            }
            
            // 获取当前登录用户ID
            String userId = StpUtil.getLoginId().toString();
            
            // 查询用户信息
            UserEntity user = userService.getById(userId);
            if (user == null) {
                return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("用户不存在");
            }
            
            // 验证原密码
            String encryptedOldPassword = DigestUtil.md5Hex(oldPassword + PASSWORD_SALT);
            if (!encryptedOldPassword.equals(user.getPassword())) {
                return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("原密码错误");
            }
            
            // 检查新密码是否与原密码相同
            String encryptedNewPassword = DigestUtil.md5Hex(newPassword + PASSWORD_SALT);
            if (encryptedNewPassword.equals(user.getPassword())) {
                return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("新密码不能与原密码相同");
            }
            
            // 更新密码
            user.setPassword(encryptedNewPassword);
            boolean success = userService.updateById(user);
            
            if (success) {
                return ResponseUtil.setE(ResponseEnum.OK).setMsg("密码修改成功");
            } else {
                return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("密码修改失败");
            }
            
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseUtil.setE(ResponseEnum.FAIL).setMsg("系统错误：" + e.getMessage());
        }
    }

}
